/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package elementsDefense.map;

import java.io.*;
import java.util.LinkedList;

/**
 *
 * @author Ricardo
 */
public class Map {
    public enum Dir {N,S,E,W};
    public final int WIDTH;
    public final int HEIGHT;
    
    public Tile[][] tile;

    private Map(int width, int height) {
        WIDTH=width;
        HEIGHT=height;
        tile=new Tile[WIDTH][HEIGHT];
    }
    
    public Map(int width, int height, int type) {
        this(width, height);
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                tile[x][y]=new Tile(x, y, type);
            }
        }
    }
    
    public Tile getEnd(){
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                if (tile[x][y].type==Tile.END){
                    return tile[x][y];
                }
            }
        }
        return null;
    }
    
    public LinkedList<Tile> getStarts(){
        LinkedList<Tile> tiles = new LinkedList<Tile>(); 
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                if (tile[x][y].type==Tile.START){
                    tiles.add(tile[x][y]);
                }
            }
        }
        return tiles;
     }
    
    public LinkedList<Tile> adjacentTiles(Tile tile, int filterType, LinkedList<Dir> directions){
        LinkedList<Tile> tiles = new LinkedList<Tile>(); 
        for (Dir dir : Dir.values()) {
            Tile tmp = getTileAt(tile, dir);
            if(tmp!=null && (tmp.type&filterType)==tmp.type) {
                tiles.add(tmp);
                if(directions!=null)directions.add(dir);
            }
        }
        return tiles;
     }
     
     public Tile getTileAt(Tile current, Dir direction){
         switch (direction) {
             case N:
                 if (current.y - 1 < 0) return null;
                 return tile[current.x][current.y - 1];
             case S:
                 if (current.y + 1 >= HEIGHT)  return null;
                 return tile[current.x][current.y + 1];
             case E:
                 if (current.x + 1 >= WIDTH) return null;
                 return tile[current.x + 1][current.y];
             case W:
                 if (current.x - 1 < 0) return null;
                 return tile[current.x - 1][current.y];
             default:
                 return null;
         }
     }
     
     
     
     
     public void save(File file) throws FileNotFoundException, IOException{
        DataOutputStream dataOutputStream = new DataOutputStream(new FileOutputStream(file));
        dataOutputStream.writeInt(WIDTH);
        dataOutputStream.writeInt(HEIGHT);
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                tile[x][y].save(dataOutputStream);
            }
        }
     }
     
     public static Map load(InputStream in) throws FileNotFoundException, IOException{
        DataInputStream dataInputStream = new DataInputStream(in);
        int WIDTH = dataInputStream.readInt();
        int HEIGHT = dataInputStream.readInt();
        Map map = new Map(WIDTH, HEIGHT);
        for (int y = 0; y < HEIGHT; y++) {
            for (int x = 0; x < WIDTH; x++) {
                map.tile[x][y]=Tile.load(x,y,dataInputStream);
            }
        }
        return map;
     }
}
